package com.basic.minio.service.impl;

import com.basic.common.core.domain.AjaxResult;
import com.basic.common.utils.file.FileUtils;
import com.basic.minio.domain.FileQO;
import com.basic.minio.domain.MinioPearVo;
import com.basic.minio.service.IFileDownloadService;
import com.basic.minio.utils.MinioUtil;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.UnsupportedEncodingException;

@Service
@Slf4j
public class FileDownloadServiceImpl implements IFileDownloadService {

    @Resource
    private MinioUtil minioUtil;



    @Override
    public ResponseEntity<byte[]> downloadMultipartFile(FileQO fileQO, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {

        String range = request.getHeader("range");
        StatObjectResponse objectResponse = minioUtil.statObject(fileQO.getFilePath());
        long startByte = 0;
        long fileSize = objectResponse.size();
        long endByte = fileSize - 1;

        if (range != null && range.contains("bytes=") && range.contains("-")) {
            range = range.substring(range.lastIndexOf("=") + 1).trim();
            String[] ranges = range.split("-");
            if (ranges.length == 1) {
                if (range.startsWith("-")) endByte = Long.parseLong(ranges[0]);
                if (range.endsWith("-")) startByte = Long.parseLong(ranges[0]);
            } else if (ranges.length == 2) {
                startByte = Long.parseLong(ranges[0]);
                endByte = Long.parseLong(ranges[1]);
            }
        }

        long contentLength = Math.min(endByte - startByte + 1, fileSize - startByte);
        response.setHeader("Accept-Ranges", "bytes");
        response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
        response.setHeader("Last-Modified", objectResponse.lastModified().toString());
        response.setHeader("Content-Disposition", "attachment;filename=" + FileUtils.percentEncode(fileQO.getFileName()));
        response.setHeader("Content-Length", String.valueOf(contentLength));
        response.setHeader("Content-Range", "bytes " + startByte + "-" + endByte + "/" + objectResponse.size());
        response.setHeader("ETag", "\"" + objectResponse.etag() + "\"");
        response.setContentType("application/octet-stream;charset=UTF-8");

        try (GetObjectResponse stream = minioUtil.getObject(objectResponse.object(), startByte, contentLength);
             BufferedOutputStream os = new BufferedOutputStream(response.getOutputStream())) {

            byte[] bytes = new byte[1024];
            long bytesWritten = 0;
            int bytesRead;
            while ((bytesRead = stream.read(bytes)) != -1) {
                if (bytesWritten + bytesRead >= contentLength) {
                    os.write(bytes, 0, (int) (contentLength - bytesWritten));
                    break;
                } else {
                    os.write(bytes, 0, bytesRead);
                    bytesWritten += bytesRead;
                }
            }
            os.flush();
            response.flushBuffer();
            return new ResponseEntity<>(HttpStatus.OK);
        } catch (Exception e) {
            log.error("文件下载失败: {}", e.getMessage(), e);
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @Override
    public MinioPearVo getChunkUrl(Integer chunkNum, String fileName, String filePath, String contentType) {
        return minioUtil.initMultiPartUpload(chunkNum, fileName, filePath, contentType);
    }

    @Override
    public AjaxResult merge(Integer chunkNum, String fileName, String contentType, String uploadId, String fileMd5, String filePath) {
        try {
            minioUtil.mergeMultipartUpload(chunkNum, contentType, uploadId, filePath);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success();
    }


}
